﻿'***************************************************************************\
' Module Name: WindowsSound.vb
' Project: SetDefaultAudioEndpoint http://sdae.codeplex.com/
' Copyright 2011 by jeff
' 
' This source is subject to the GNU General Public License version 2 (GPLv2).
' See http://www.gnu.org/licenses/gpl-2.0.html.
' All other rights reserved.
' 
' THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, 
' EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED 
' WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
'***************************************************************************/

Public Class WindowsSound
  Implements IDisposable

  'WindowsSound is a facade, a "simple interface to a complex subsystem" (GoF)

  Private myDisposedValue As Boolean
  Private myWindowsSoundImplementation As IWindowsSoundImplementation

  Public Sub SetDefaultAudioPlaybackEndpoint(ByVal index As Integer)
    Dim endpoint As IAudioEndpoint = WindowsSound.SearchDevicesForAudioEndpoint(index, Me.PlaybackEndpoints)
    Me.WindowsSoundImplementation.SetDefaultPlaybackEndpoint(endpoint)
  End Sub

  Public Sub SetDefaultAudioPlaybackEndpoint(ByVal name As String)
    Dim endpoint As IAudioEndpoint = WindowsSound.SearchDevicesForAudioEndpoint(name, Me.PlaybackEndpoints)
    Me.WindowsSoundImplementation.SetDefaultPlaybackEndpoint(endpoint)
  End Sub

  Public Sub SetDefaultAudioRecordingEndpoint(ByVal index As Integer)
    Dim endpoint As IAudioEndpoint = WindowsSound.SearchDevicesForAudioEndpoint(index, Me.RecordingEndpoints)
    Me.WindowsSoundImplementation.SetDefaultRecordingEndpoint(endpoint)
  End Sub

  Public Sub SetDefaultAudioRecordingEndpoint(ByVal name As String)
    Dim endpoint As IAudioEndpoint = WindowsSound.SearchDevicesForAudioEndpoint(name, Me.RecordingEndpoints)
    Me.WindowsSoundImplementation.SetDefaultRecordingEndpoint(endpoint)
  End Sub

  Private Shared Function SearchDevicesForAudioEndpoint(ByVal index As Integer, ByVal devices As IAudioEndpointList) As IAudioEndpoint
    Try
      Return devices.ElementAt(index)
    Catch ex As InvalidOperationException
      Dim message As String = String.Format(Globalization.CultureInfo.CurrentCulture, "The audio endpoint with index '{0}' could not be found.", index.ToString(Globalization.CultureInfo.CurrentCulture))
      Throw New WindowsSoundException(message, ex)
    End Try
  End Function

  Private Shared Function SearchDevicesForAudioEndpoint(ByVal name As String, ByVal devices As IAudioEndpointList) As IAudioEndpoint
    Try
      Return devices.First(Function(item) item.Name = name)
    Catch ex As InvalidOperationException
      Dim message As String = String.Format(Globalization.CultureInfo.CurrentCulture, "The audio endpoint with name '{0}' could not be found.", name)
      Throw New WindowsSoundException(message, ex)
    End Try
  End Function

  'private shared sub ThrowAudioEndpointNotFoundException(message as string, devices as

  Private ReadOnly Property PlaybackEndpoints() As IAudioEndpointList
    Get
      Return Me.WindowsSoundImplementation.PlaybackEndpoints
    End Get
  End Property

  Private ReadOnly Property RecordingEndpoints() As IAudioEndpointList
    Get
      Return Me.WindowsSoundImplementation.RecordingEndpoints
    End Get
  End Property

  Private ReadOnly Property WindowsSoundImplementation() As IWindowsSoundImplementation
    Get
      If (Me.myWindowsSoundImplementation Is Nothing) Then
        Me.myWindowsSoundImplementation = WindowsSound.DefaultWindowsSoundImplementation
      End If

      Return Me.myWindowsSoundImplementation
    End Get
  End Property

  Private Shared Function DefaultWindowsSoundImplementation() As IWindowsSoundImplementation
    Return Windows7.SoundWindow.Open
  End Function

  'Private Shared Sub ThrowWindowsSoundException(ByVal ex As ElementNotAvailableException)
  '  Throw New WindowsSoundException("There was an error processing the request.", ex)
  'End Sub

  ' IDisposable
  Protected Overridable Sub Dispose(ByVal disposing As Boolean)
    If Not Me.myDisposedValue Then
      If disposing Then
        ' free other state (managed objects)
        If ((Me.myWindowsSoundImplementation IsNot Nothing)) Then
          Me.myWindowsSoundImplementation.Dispose()
        End If
      End If

      ' TODO: free your own state (unmanaged objects)
      ' set large fields to null
      Me.myWindowsSoundImplementation = Nothing
    End If
    Me.myDisposedValue = True
  End Sub

#Region " IDisposable Support "
  ' This code added by Visual Basic to correctly implement the disposable pattern.
  Public Sub Dispose() Implements IDisposable.Dispose
    ' Do not change this code.  Put cleanup code in Dispose(ByVal disposing As Boolean) above.
    Dispose(True)
    GC.SuppressFinalize(Me)
  End Sub
#End Region

End Class
